<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<!-- 
	Copyright (C) 2007, 2008, 2009, 2010, 2011. PARP Research Group.
	<http://perception.inf.um.es>
	University of Murcia, Spain.

	This file is part of the QVision library.

	QVision is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as
	published by the Free Software Foundation, version 3 of the License.

	QVision is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with QVision. If not, see <http://www.gnu.org/licenses/>.
-->

<html><head><meta http-equiv="content-Type" content="text/html;charset=UTF-8">
<title>QVision: Qt&#39;s Image, Video and Computer Vision Library</title>
<meta name="title" content="QVision" />
<meta name="dc.title" content="QVision" />
<meta name="url" content="http://perception.inf.um.es/QVision" />
<meta name="author" content="PARP Research Group - http://perception.inf.um.es" />
<meta name="revisit-after" content="30 DAYS"/>
<meta name="robots" content="index,follow"/>
<meta name="classification" content="*">
<meta name="rating" content="Safe For Kids">
<meta name="distribution" content="GLOBAL"/>
<meta name="description" content="Qt's Image, Video and Computer Vision Library"/>
<meta name="page-topic" content="Computer Vision research and prototype programming"/>
<meta name="geo.country" content="ES" />

<!--
Keywords:
By license:		open source, gnu, lgpl, gpl, free
By theme:		computer vision, image processing, robotics, programming, source, development
By usage:		library, toolkit, framework, prototype, application
By programming specs:	object oriented, c++, block programming, reusability, gui, graphical, parallel computing, high performance, GPU, prototyping
Interoperability with:	Qt, GSL, GNU Scientific library, OpenCV, CGAL, QWT, CUDA, mplayer, IPP, Intel Image Performance Primitives, blas, lapack
Functionallity:		image features, matrix algebra, projective geometry, mser, function minimization, function optimization, canny operator, harris operator, corner detection, performance evaluation, cpu usage, graphical interface
Main data-types:	matrix, vector, tensor, quaternion, image, polyline
Video sources:		webcam, camera, stream
Devices:		embedded, desktop computer, laptop, mini-laptop
Authors:		PARP research group. University of Murcia, Spain.
-->

<meta name="keywords" content="augmented reality, sfm, structure from motion, open source, gnu, lgpl, gpl, free, computer vision, image processing, robotics, programming, source, development, library, toolkit, framework, prototype, application, object oriented, c++, block programming, reusability, gui, graphical, parallel computing, high performance, GPU, prototyping, Qt, GSL, GNU Scientific library, OpenCV, CGAL, QWT, CUDA, mplayer, IPP, Intel Image Performance Primitives, blas, lapack, image features, matrix algebra, projective geometry, mser, function minimization, function optimization, canny operator, harris operator, corner detection, performance evaluation, cpu usage, graphical interface, matrix, vector, tensor, quaternion, image, polyline, webcam, camera, stream, embedded, desktop computer, laptop, mini-laptop, University of Murcia, Spain, PARP research group, vision por computador"/>
<meta http-equiv="keywords" content="augmented reality, sfm, structure from motion, open source, gnu, lgpl, gpl, free, computer vision, image processing, robotics, programming, source, development, library, toolkit, framework, prototype, application, object oriented, c++, block programming, reusability, gui, graphical, parallel computing, high performance, GPU, prototyping, Qt, GSL, GNU Scientific library, OpenCV, CGAL, QWT, CUDA, mplayer, IPP, Intel Image Performance Primitives, blas, lapack, image features, matrix algebra, projective geometry, mser, function minimization, function optimization, canny operator, harris operator, corner detection, performance evaluation, cpu usage, graphical interface, matrix, vector, tensor, quaternion, image, polyline, webcam, camera, stream, embedded, desktop computer, laptop, mini-laptop, University of Murcia, Spain, PARP research group, vision por computador"/>
<meta http-equiv="pragma" content="no-cache"/>
<meta http-equiv="title" content="QVision"/>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="tabs.css" rel="stylesheet" type="text/css" />
<link rel="shortcut icon" href="favicon.ico" />
</head><body>

<table width="100%"><tr>
	<td><a href="http://perception.inf.um.es/"><img src="parp.png" border="0" /> <big>PARP Research Group</big></a></td>
	<td align="right"><a href="http://www.um.es/"><big>Universidad de Murcia</big> <img src="um.png" border="0" /></a></td>
</tr></table>

<hr /><br />

<table width="95%" align="center"><tr><td>

<!-- Generated by Doxygen 1.6.3 -->
<script type="text/javascript"><!--
var searchBox = new SearchBox("searchBox", "search",false,'Search');
--></script>
<div class="navigation" id="top">
  <div class="tabs">
    <ul>
      <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
      <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
      <li><a href="modules.html"><span>Modules</span></a></li>
      <li><a href="annotated.html"><span>Classes</span></a></li>
      <li class="current"><a href="files.html"><span>Files</span></a></li>
      <li>
        <div id="MSearchBox" class="MSearchBoxInactive">
          <form id="FSearchBox" action="search.php" method="get">
            <img id="MSearchSelect" src="search/search.png" alt=""/>
            <input type="text" id="MSearchField" name="query" value="Search" size="20" accesskey="S" 
                   onfocus="searchBox.OnSearchFieldFocus(true)" 
                   onblur="searchBox.OnSearchFieldFocus(false)"/>
          </form>
        </div>
      </li>
    </ul>
  </div>
  <div class="tabs">
    <ul>
      <li><a href="files.html"><span>File&nbsp;List</span></a></li>
      <li><a href="globals.html"><span>File&nbsp;Members</span></a></li>
    </ul>
  </div>
<h1>src/qvmath/qvtensor.cpp</h1><a href="qvtensor_8cpp.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
<a name="l00002"></a>00002 <span class="comment"> *      Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012. PARP Research Group.</span>
<a name="l00003"></a>00003 <span class="comment"> *      &lt;http://perception.inf.um.es&gt;</span>
<a name="l00004"></a>00004 <span class="comment"> *      University of Murcia, Spain.</span>
<a name="l00005"></a>00005 <span class="comment"> *</span>
<a name="l00006"></a>00006 <span class="comment"> *      This file is part of the QVision library.</span>
<a name="l00007"></a>00007 <span class="comment"> *</span>
<a name="l00008"></a>00008 <span class="comment"> *      QVision is free software: you can redistribute it and/or modify</span>
<a name="l00009"></a>00009 <span class="comment"> *      it under the terms of the GNU Lesser General Public License as</span>
<a name="l00010"></a>00010 <span class="comment"> *      published by the Free Software Foundation, version 3 of the License.</span>
<a name="l00011"></a>00011 <span class="comment"> *</span>
<a name="l00012"></a>00012 <span class="comment"> *      QVision is distributed in the hope that it will be useful,</span>
<a name="l00013"></a>00013 <span class="comment"> *      but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<a name="l00014"></a>00014 <span class="comment"> *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span>
<a name="l00015"></a>00015 <span class="comment"> *      GNU Lesser General Public License for more details.</span>
<a name="l00016"></a>00016 <span class="comment"> *</span>
<a name="l00017"></a>00017 <span class="comment"> *      You should have received a copy of the GNU Lesser General Public</span>
<a name="l00018"></a>00018 <span class="comment"> *      License along with QVision. If not, see &lt;http://www.gnu.org/licenses/&gt;.</span>
<a name="l00019"></a>00019 <span class="comment"> */</span>
<a name="l00020"></a>00020 
<a name="l00024"></a>00024 
<a name="l00025"></a>00025 <span class="preprocessor">#include &lt;qvmath.h&gt;</span>
<a name="l00026"></a>00026 <span class="preprocessor">#include &lt;QVTensor&gt;</span>
<a name="l00027"></a>00027 
<a name="l00028"></a><a class="code" href="classQVTensor.html#a66f3349e05d25669238e817363af2829">00028</a> <span class="keywordtype">bool</span> <a class="code" href="classQVTensor.html#a66f3349e05d25669238e817363af2829" title="Check equivalence between tensors.">QVTensor::equals</a>(<span class="keyword">const</span> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> &amp;tensor)<span class="keyword"> const</span>
<a name="l00029"></a>00029 <span class="keyword">        </span>{
<a name="l00030"></a>00030         Q_ASSERT(dims.size() == indexIds.size());
<a name="l00031"></a>00031         Q_ASSERT(tensor.dims.size() == tensor.indexIds.size());
<a name="l00032"></a>00032 
<a name="l00034"></a>00034 
<a name="l00035"></a>00035         <span class="comment">// Check valences for both tensors are equivalent</span>
<a name="l00036"></a>00036         <span class="keywordflow">if</span> (dims != tensor.dims)
<a name="l00037"></a>00037                 <span class="keywordflow">return</span> <span class="keyword">false</span>;
<a name="l00038"></a>00038 
<a name="l00039"></a>00039         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; indexIds.size(); i++)
<a name="l00040"></a>00040                 <span class="keywordflow">if</span> (indexIds[i] * tensor.indexIds[i] &lt; 0 )
<a name="l00041"></a>00041                         <span class="keywordflow">return</span> <span class="keyword">false</span>;
<a name="l00042"></a>00042 
<a name="l00043"></a>00043         <span class="comment">// Check data in both tensors is equal</span>
<a name="l00044"></a>00044         <span class="keyword">const</span> <span class="keywordtype">double</span>    *data1 = <a class="code" href="classQVTensor.html#a9e75752b76652d2a1ebc64dbc5d0df49" title="Gets a read-only reference to the data buffer of the tensor.">getReadData</a>(),
<a name="l00045"></a>00045                         *data2 = tensor.<a class="code" href="classQVTensor.html#a9e75752b76652d2a1ebc64dbc5d0df49" title="Gets a read-only reference to the data buffer of the tensor.">getReadData</a>();
<a name="l00046"></a>00046 
<a name="l00047"></a>00047         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; <a class="code" href="classQVTensor.html#aaf731ea26d29371aedf67e02a1f47983" title="Gets the size of the data array.">getDataSize</a>(); i++)
<a name="l00048"></a>00048                 <span class="keywordflow">if</span> (data1[i] != data2[i])
<a name="l00049"></a>00049                         <span class="keywordflow">return</span> <span class="keyword">false</span>;
<a name="l00050"></a>00050 
<a name="l00051"></a>00051         <span class="keywordflow">return</span> <span class="keyword">true</span>;
<a name="l00052"></a>00052         }
<a name="l00053"></a>00053 
<a name="l00054"></a><a class="code" href="classQVTensor.html#a05457fb8f5a27bd8dfa0fb960b306d4a">00054</a> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> <a class="code" href="classQVTensor.html#a05457fb8f5a27bd8dfa0fb960b306d4a" title="Obtains the tensor product of two tensors.">QVTensor::tensorProduct</a>(<span class="keyword">const</span> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> &amp;tensor)<span class="keyword"> const</span>
<a name="l00055"></a>00055 <span class="keyword">        </span>{
<a name="l00056"></a>00056         Q_ASSERT(dims.size() == indexIds.size());
<a name="l00057"></a>00057 
<a name="l00058"></a>00058         QVTensorValence indexList;
<a name="l00059"></a>00059 
<a name="l00060"></a>00060         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; <a class="code" href="classQVTensor.html#ada0f3000987c85bbaaa3c02e4b69aada" title="Gets valence of the tensor.">getValence</a>().size(); i++)
<a name="l00061"></a>00061                 indexList.append(<a class="code" href="classQVTensor.html#ada0f3000987c85bbaaa3c02e4b69aada" title="Gets valence of the tensor.">getValence</a>()[i]);
<a name="l00062"></a>00062 
<a name="l00063"></a>00063         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; tensor.<a class="code" href="classQVTensor.html#ada0f3000987c85bbaaa3c02e4b69aada" title="Gets valence of the tensor.">getValence</a>().size(); i++)
<a name="l00064"></a>00064                 indexList.append(tensor.<a class="code" href="classQVTensor.html#ada0f3000987c85bbaaa3c02e4b69aada" title="Gets valence of the tensor.">getValence</a>()[i]);
<a name="l00065"></a>00065 
<a name="l00066"></a>00066         <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> result(indexList);
<a name="l00067"></a>00067 
<a name="l00068"></a>00068         <span class="keyword">const</span> <span class="keywordtype">double</span>    *src1Data = <a class="code" href="classQVTensor.html#a9e75752b76652d2a1ebc64dbc5d0df49" title="Gets a read-only reference to the data buffer of the tensor.">getReadData</a>();
<a name="l00069"></a>00069         <span class="keyword">const</span> <span class="keywordtype">double</span>    *src2Data = tensor.<a class="code" href="classQVTensor.html#a9e75752b76652d2a1ebc64dbc5d0df49" title="Gets a read-only reference to the data buffer of the tensor.">getReadData</a>();
<a name="l00070"></a>00070         <span class="keywordtype">double</span>          *destData = result.<a class="code" href="classQVTensor.html#a9d5c2f2d4fd11123354d7568400d2b8e" title="Gets a reference of the data buffer of the tensor for read and write accesses.">getWriteData</a>();
<a name="l00071"></a>00071         <span class="keyword">const</span> <span class="keywordtype">int</span>       vectorSize = tensor.<a class="code" href="classQVTensor.html#aaf731ea26d29371aedf67e02a1f47983" title="Gets the size of the data array.">getDataSize</a>();
<a name="l00072"></a>00072 
<a name="l00073"></a>00073         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0, destIndex = 0; i &lt; <a class="code" href="classQVTensor.html#aaf731ea26d29371aedf67e02a1f47983" title="Gets the size of the data array.">getDataSize</a>(); i++, destIndex += vectorSize)
<a name="l00074"></a>00074                 {
<a name="l00075"></a>00075                 cblas_dcopy(vectorSize, src2Data, 1, &amp;(destData[destIndex]), 1);
<a name="l00076"></a>00076                 cblas_dscal(vectorSize, src1Data[i], &amp;(destData[destIndex]), 1);
<a name="l00077"></a>00077                 }
<a name="l00078"></a>00078 
<a name="l00079"></a>00079         <span class="keywordflow">return</span> result;
<a name="l00080"></a>00080         }
<a name="l00081"></a>00081 
<a name="l00082"></a><a class="code" href="classQVTensor.html#ac1d43563ea2215db9d9e710cba7e0246">00082</a> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> <a class="code" href="classQVTensor.html#ac1d43563ea2215db9d9e710cba7e0246" title="Tensor add.">QVTensor::add</a>(<span class="keyword">const</span> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> &amp;tensor)<span class="keyword"> const</span>
<a name="l00083"></a>00083 <span class="keyword">        </span>{
<a name="l00084"></a>00084         Q_ASSERT(dims.size() == indexIds.size());
<a name="l00086"></a>00086 
<a name="l00087"></a>00087         <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> result = *<span class="keyword">this</span>;
<a name="l00088"></a>00088 
<a name="l00089"></a>00089         <span class="keyword">const</span> <span class="keywordtype">double</span>    *tensorData = tensor.<a class="code" href="classQVTensor.html#a9e75752b76652d2a1ebc64dbc5d0df49" title="Gets a read-only reference to the data buffer of the tensor.">getReadData</a>();
<a name="l00090"></a>00090         <span class="keywordtype">double</span>          *resultData = result.getWriteData();
<a name="l00091"></a>00091 <span class="comment">//      const int       dataSize = tensor.getDataSize();</span>
<a name="l00092"></a>00092 
<a name="l00094"></a>00094 
<a name="l00095"></a>00095         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; <a class="code" href="classQVTensor.html#aaf731ea26d29371aedf67e02a1f47983" title="Gets the size of the data array.">getDataSize</a>(); i++)
<a name="l00096"></a>00096                 resultData[i] += tensorData[i];
<a name="l00097"></a>00097 
<a name="l00098"></a>00098         <span class="keywordflow">return</span> result;
<a name="l00099"></a>00099         }
<a name="l00100"></a>00100 
<a name="l00101"></a><a class="code" href="classQVTensor.html#a9c310f3902d33a4572b36147b887a3a5">00101</a> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> <a class="code" href="classQVTensor.html#a9c310f3902d33a4572b36147b887a3a5" title="Tensor substraction.">QVTensor::substract</a>(<span class="keyword">const</span> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> &amp;tensor)<span class="keyword"> const</span>
<a name="l00102"></a>00102 <span class="keyword">        </span>{
<a name="l00103"></a>00103         Q_ASSERT(dims.size() == indexIds.size());
<a name="l00106"></a>00106 
<a name="l00107"></a>00107         <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> result = *<span class="keyword">this</span>;
<a name="l00108"></a>00108 
<a name="l00109"></a>00109         <span class="keyword">const</span> <span class="keywordtype">double</span>    *tensorData = tensor.<a class="code" href="classQVTensor.html#a9e75752b76652d2a1ebc64dbc5d0df49" title="Gets a read-only reference to the data buffer of the tensor.">getReadData</a>();
<a name="l00110"></a>00110         <span class="keywordtype">double</span>          *resultData = result.getWriteData();
<a name="l00111"></a>00111 <span class="comment">//      const int       dataSize = tensor.getDataSize();</span>
<a name="l00112"></a>00112 
<a name="l00113"></a>00113         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; <a class="code" href="classQVTensor.html#aaf731ea26d29371aedf67e02a1f47983" title="Gets the size of the data array.">getDataSize</a>(); i++)
<a name="l00114"></a>00114                 resultData[i] -= tensorData[i];
<a name="l00115"></a>00115 
<a name="l00116"></a>00116         <span class="keywordflow">return</span> result;
<a name="l00117"></a>00117         }
<a name="l00118"></a>00118 
<a name="l00119"></a><a class="code" href="classQVTensor.html#ac3ab1408a9ae9b32c01dca061d422ddf">00119</a> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> <a class="code" href="classQVTensor.html#ac3ab1408a9ae9b32c01dca061d422ddf" title="Obtains the inner product of two tensors.">QVTensor::innerProduct</a>(<span class="keyword">const</span> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> &amp;tensor)<span class="keyword"> const</span>
<a name="l00120"></a>00120 <span class="keyword">        </span>{
<a name="l00121"></a>00121         Q_ASSERT(dims.size() == indexIds.size());
<a name="l00122"></a>00122 
<a name="l00123"></a>00123         <span class="keyword">const</span> QMap&lt;int, QVector&lt;int&gt; &gt;  indexesQVTensor1 = <a class="code" href="classQVTensor.html#ada0f3000987c85bbaaa3c02e4b69aada" title="Gets valence of the tensor.">getValence</a>().getIndexesPositions(),
<a name="l00124"></a>00124                                         indexesQVTensor2 = tensor.<a class="code" href="classQVTensor.html#ada0f3000987c85bbaaa3c02e4b69aada" title="Gets valence of the tensor.">getValence</a>().getIndexesPositions();
<a name="l00125"></a>00125 
<a name="l00126"></a>00126         <span class="keywordtype">int</span> actualIndexSize = 0, actualQVTensor1Position = -1, actualQVTensor2Position = -1;
<a name="l00127"></a>00127 
<a name="l00128"></a>00128         QMapIterator&lt; int, QVector&lt;int&gt; &gt; idx(indexesQVTensor1);
<a name="l00129"></a>00129 
<a name="l00130"></a>00130         <span class="keywordflow">while</span> (idx.hasNext())
<a name="l00131"></a>00131                 {
<a name="l00132"></a>00132                 idx.next();
<a name="l00133"></a>00133                 <span class="keyword">const</span> <span class="keywordtype">int</span> key = idx.key();
<a name="l00134"></a>00134                 <span class="keyword">const</span> QVector&lt;int&gt; positionsIndex1 = indexesQVTensor1[key], positionsIndex2 = indexesQVTensor2[key];
<a name="l00135"></a>00135 
<a name="l00136"></a>00136                 <span class="keywordflow">if</span> (positionsIndex1.size() &gt; 1)
<a name="l00137"></a>00137                         std::cerr &lt;&lt; <span class="stringliteral">&quot;ERROR, índice repetido en primer tensor de producto *.&quot;</span> &lt;&lt; std::endl;
<a name="l00138"></a>00138                 <span class="keywordflow">else</span> <span class="keywordflow">if</span> (positionsIndex2.size() &gt; 1)
<a name="l00139"></a>00139                         std::cerr &lt;&lt; <span class="stringliteral">&quot;ERROR, índice repetido en segundo tensor de producto *.&quot;</span> &lt;&lt; std::endl;
<a name="l00140"></a>00140 
<a name="l00141"></a>00141                 <span class="keywordflow">else</span> <span class="keywordflow">if</span> (positionsIndex1.size() == 1 &amp;&amp; positionsIndex2.size() == 1)
<a name="l00142"></a>00142                         {
<a name="l00143"></a>00143                         <span class="keyword">const</span> <span class="keywordtype">int</span> position1 = positionsIndex1[0], position2 = positionsIndex2[0];
<a name="l00144"></a>00144                         <span class="keyword">const</span> <span class="keywordtype">int</span> indexSize = dims[position1];
<a name="l00145"></a>00145 
<a name="l00146"></a>00146                         <span class="keywordflow">if</span> (indexIds[position1] == tensor.indexIds[position2])
<a name="l00147"></a>00147                                 std::cerr &lt;&lt; <span class="stringliteral">&quot;ERROR, índices iguales en ambos tensores en producto *.&quot;</span> &lt;&lt; std::endl;
<a name="l00148"></a>00148                         <span class="keywordflow">else</span>    <span class="comment">// we have a candidate index.</span>
<a name="l00149"></a>00149                                 <span class="keywordflow">if</span> (indexSize &gt; actualIndexSize)
<a name="l00150"></a>00150                                         {
<a name="l00151"></a>00151                                         actualIndexSize = indexSize;
<a name="l00152"></a>00152                                         actualQVTensor1Position = position1;
<a name="l00153"></a>00153                                         actualQVTensor2Position = position2;
<a name="l00154"></a>00154                                         }
<a name="l00155"></a>00155                         }
<a name="l00156"></a>00156                 }
<a name="l00157"></a>00157 
<a name="l00158"></a>00158         <span class="keywordflow">if</span> (actualQVTensor1Position == -1 &amp;&amp; actualQVTensor2Position == -1)
<a name="l00159"></a>00159                 <span class="keywordflow">return</span> this-&gt;<a class="code" href="classQVTensor.html#a05457fb8f5a27bd8dfa0fb960b306d4a" title="Obtains the tensor product of two tensors.">tensorProduct</a>(tensor).contract();
<a name="l00160"></a>00160         <span class="keywordflow">else</span>    <span class="keywordflow">if</span> (actualQVTensor1Position == -1 || actualQVTensor2Position == -1)
<a name="l00161"></a>00161                 std::cerr &lt;&lt; <span class="stringliteral">&quot;ERROR, posición para el índice dominante no definida en producto *.&quot;</span> &lt;&lt; std::endl;
<a name="l00162"></a>00162 
<a name="l00163"></a>00163         <span class="comment">// Move dominant index to end and start of the tensors</span>
<a name="l00164"></a>00164         QVTensorValence indexList1 = this-&gt;<a class="code" href="classQVTensor.html#ada0f3000987c85bbaaa3c02e4b69aada" title="Gets valence of the tensor.">getValence</a>(), indexList2 = tensor.<a class="code" href="classQVTensor.html#ada0f3000987c85bbaaa3c02e4b69aada" title="Gets valence of the tensor.">getValence</a>();
<a name="l00165"></a>00165 
<a name="l00166"></a>00166         <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a>        t1 = this-&gt;<a class="code" href="classQVTensor.html#a6ca73279da9ca3a3914d385faeac0ccd" title="Change the order of the indexes in the tensor.">transpose</a>(actualQVTensor1Position, dims.size()-1), t2 = tensor.<a class="code" href="classQVTensor.html#a6ca73279da9ca3a3914d385faeac0ccd" title="Change the order of the indexes in the tensor.">transpose</a>(actualQVTensor2Position, 0);
<a name="l00167"></a>00167 
<a name="l00168"></a>00168         indexList1.removeAt(actualQVTensor1Position);
<a name="l00169"></a>00169         indexList2.removeAt(actualQVTensor2Position);
<a name="l00170"></a>00170 
<a name="l00171"></a>00171         QVTensorValence resultIndexList;
<a name="l00172"></a>00172         resultIndexList &lt;&lt; indexList1 &lt;&lt; indexList2;
<a name="l00173"></a>00173         <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> result(resultIndexList);
<a name="l00174"></a>00174 
<a name="l00175"></a>00175         <span class="keyword">const</span> <span class="keywordtype">int</span> k = t2.dims[0], m = t1.<a class="code" href="classQVTensor.html#aaf731ea26d29371aedf67e02a1f47983" title="Gets the size of the data array.">getDataSize</a>() / k, n = t2.getDataSize() / k;
<a name="l00176"></a>00176  
<a name="l00177"></a>00177         cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
<a name="l00178"></a>00178                         m, n, k, 1.0,
<a name="l00179"></a>00179                         t1.<a class="code" href="classQVTensor.html#a9e75752b76652d2a1ebc64dbc5d0df49" title="Gets a read-only reference to the data buffer of the tensor.">getReadData</a>(), k,
<a name="l00180"></a>00180                         t2.getReadData(), n, 0.0,
<a name="l00181"></a>00181                         result.<a class="code" href="classQVTensor.html#a9d5c2f2d4fd11123354d7568400d2b8e" title="Gets a reference of the data buffer of the tensor for read and write accesses.">getWriteData</a>(), n);
<a name="l00182"></a>00182         
<a name="l00183"></a>00183         <span class="keywordflow">return</span> result;
<a name="l00184"></a>00184         };
<a name="l00185"></a>00185 
<a name="l00186"></a><a class="code" href="classQVTensor.html#a5fca8e41cab78d5f664b33dc355abbb9">00186</a> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> <a class="code" href="classQVTensor.html#a5fca8e41cab78d5f664b33dc355abbb9" title="Obtains the outer product of two tensors.">QVTensor::outerProduct</a>(<span class="keyword">const</span> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> &amp;<span class="comment">/*tensor*/</span>)<span class="keyword"> const</span>
<a name="l00187"></a>00187 <span class="keyword">        </span>{
<a name="l00189"></a>00189         <span class="keywordflow">return</span> *<span class="keyword">this</span>;
<a name="l00190"></a>00190         }
<a name="l00191"></a>00191 
<a name="l00192"></a><a class="code" href="classQVTensor.html#afce34958c46236f2332c04c886d54333">00192</a> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> <a class="code" href="classQVTensor.html#afce34958c46236f2332c04c886d54333" title="Index renaming and contracting.">QVTensor::renameIndexes</a>(<span class="keyword">const</span> QVTensorValence &amp;indexList)<span class="keyword"> const</span>
<a name="l00193"></a>00193 <span class="keyword">        </span>{
<a name="l00194"></a>00194         Q_ASSERT(dims.size() == indexIds.size());
<a name="l00197"></a>00197         <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> result = *<span class="keyword">this</span>;
<a name="l00198"></a>00198 
<a name="l00199"></a>00199         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; indexList.size(); i++)
<a name="l00200"></a>00200                 result.indexIds[i] = indexList.at(i).id;
<a name="l00201"></a>00201 
<a name="l00202"></a>00202         <span class="keywordflow">return</span> result.contract();
<a name="l00203"></a>00203         }
<a name="l00204"></a>00204 
<a name="l00206"></a>00206 
<a name="l00207"></a><a class="code" href="classQVTensor.html#ada0f3000987c85bbaaa3c02e4b69aada">00207</a> QVTensorValence <a class="code" href="classQVTensor.html#ada0f3000987c85bbaaa3c02e4b69aada" title="Gets valence of the tensor.">QVTensor::getValence</a>()<span class="keyword">  const</span>
<a name="l00208"></a>00208 <span class="keyword">        </span>{
<a name="l00209"></a>00209         Q_ASSERT(dims.size() == indexIds.size());
<a name="l00210"></a>00210 
<a name="l00211"></a>00211         QVTensorValence result;
<a name="l00212"></a>00212         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; dims.size(); i++)
<a name="l00213"></a>00213                 result.append(<a class="code" href="classQVTensorIndex.html" title="Indexes for tensors.">QVTensorIndex</a>(dims[i], indexIds[i]));
<a name="l00214"></a>00214         <span class="keywordflow">return</span> result;
<a name="l00215"></a>00215         }
<a name="l00216"></a>00216 
<a name="l00217"></a><a class="code" href="classQVTensor.html#abeec4ea63ea5cac0bec9985b89d6c11b">00217</a> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> <a class="code" href="classQVTensor.html#abeec4ea63ea5cac0bec9985b89d6c11b" title="Get a subtensor from a tensor.">QVTensor::slice</a>(<span class="keyword">const</span> QVTensorIndexValues &amp;indexRangeList)<span class="keyword"> const</span>
<a name="l00218"></a>00218 <span class="keyword">        </span>{
<a name="l00219"></a>00219         Q_ASSERT(dims.size() == indexIds.size());
<a name="l00220"></a>00220         <span class="keyword">const</span> <span class="keywordtype">int</span> numDims = dims.size();
<a name="l00221"></a>00221 
<a name="l00222"></a>00222         QVTensorIterator tensorIterator(dims, indexIds, indexRangeList);
<a name="l00223"></a>00223         QVTensorValence idxList;
<a name="l00224"></a>00224 
<a name="l00225"></a>00225         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i=0; i&lt; numDims; i++)
<a name="l00226"></a>00226                 <span class="keywordflow">if</span> (tensorIterator.numElementsDimension(i) &gt; 1)
<a name="l00227"></a>00227                         idxList.append(<a class="code" href="classQVTensorIndex.html" title="Indexes for tensors.">QVTensorIndex</a>(tensorIterator.numElementsDimension(i), indexIds[i]));
<a name="l00228"></a>00228 
<a name="l00229"></a>00229         <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> result(idxList);
<a name="l00230"></a>00230 
<a name="l00231"></a>00231         <span class="keywordtype">double</span> <span class="keyword">const</span>    *srcData = <a class="code" href="classQVTensor.html#a9e75752b76652d2a1ebc64dbc5d0df49" title="Gets a read-only reference to the data buffer of the tensor.">getReadData</a>();
<a name="l00232"></a>00232         <span class="keywordtype">double</span>          *destData = result.<a class="code" href="classQVTensor.html#a9d5c2f2d4fd11123354d7568400d2b8e" title="Gets a reference of the data buffer of the tensor for read and write accesses.">getWriteData</a>();
<a name="l00233"></a>00233         <span class="keywordtype">int</span>             destIndexValue = -tensorIterator.getVectorSize();
<a name="l00234"></a>00234 
<a name="l00235"></a>00235         <span class="keywordflow">do</span> cblas_dcopy(tensorIterator.getVectorSize(), &amp;(srcData[tensorIterator.getVectorIndex()]), 1, &amp;(destData[destIndexValue += tensorIterator.getVectorSize()]),1);
<a name="l00236"></a>00236         <span class="keywordflow">while</span> (tensorIterator.nextVector());
<a name="l00237"></a>00237 
<a name="l00238"></a>00238         <span class="keywordflow">return</span> result;
<a name="l00239"></a>00239         }
<a name="l00240"></a>00240 
<a name="l00241"></a><a class="code" href="classQVTensor.html#a750367d97c7647c1dc5c9af8b1f5ba11">00241</a> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> <a class="code" href="classQVTensor.html#a6ca73279da9ca3a3914d385faeac0ccd" title="Change the order of the indexes in the tensor.">QVTensor::transpose</a>(<span class="keyword">const</span> <a class="code" href="classQVTensorIndex.html" title="Indexes for tensors.">QVTensorIndex</a> &amp;index1, <span class="keyword">const</span> <a class="code" href="classQVTensorIndex.html" title="Indexes for tensors.">QVTensorIndex</a> &amp;index2)<span class="keyword"> const</span>
<a name="l00242"></a>00242 <span class="keyword">        </span>{
<a name="l00243"></a>00243         Q_ASSERT(dims.size() == indexIds.size());
<a name="l00244"></a>00244 
<a name="l00245"></a>00245         <span class="keywordtype">int</span> index1Position = -1, index2Position = -1;
<a name="l00246"></a>00246 
<a name="l00247"></a>00247         <span class="keywordflow">if</span> (index1.id == index2.id)
<a name="l00248"></a>00248                 <span class="keywordflow">return</span> *<span class="keyword">this</span>;
<a name="l00249"></a>00249 
<a name="l00250"></a>00250         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> n = 0; n&lt; dims.size(); n++)
<a name="l00251"></a>00251                 {
<a name="l00252"></a>00252                 <span class="keywordflow">if</span> (indexIds[n] == index1.id)
<a name="l00253"></a>00253                         index1Position = n;
<a name="l00254"></a>00254                 <span class="keywordflow">if</span> (indexIds[n] == index2.id)
<a name="l00255"></a>00255                         index2Position = n;
<a name="l00256"></a>00256                 }
<a name="l00257"></a>00257 
<a name="l00258"></a>00258         <span class="keywordflow">if</span> (index1Position == -1 || index2Position == -1)
<a name="l00259"></a>00259                 std::cerr &lt;&lt; <span class="stringliteral">&quot;ERROR, index not found in transpose.&quot;</span> &lt;&lt; std::endl;
<a name="l00260"></a>00260 
<a name="l00261"></a>00261         <span class="keywordflow">return</span> <a class="code" href="classQVTensor.html#a6ca73279da9ca3a3914d385faeac0ccd" title="Change the order of the indexes in the tensor.">transpose</a>(index1Position, index2Position);
<a name="l00262"></a>00262         }
<a name="l00263"></a>00263 
<a name="l00264"></a><a class="code" href="classQVTensor.html#a6ca73279da9ca3a3914d385faeac0ccd">00264</a> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> <a class="code" href="classQVTensor.html#a6ca73279da9ca3a3914d385faeac0ccd" title="Change the order of the indexes in the tensor.">QVTensor::transpose</a>(<span class="keyword">const</span> QVTensorValence &amp;indexList)<span class="keyword"> const</span>
<a name="l00265"></a>00265 <span class="keyword">        </span>{
<a name="l00266"></a>00266         Q_ASSERT(dims.size() == indexIds.size());
<a name="l00267"></a>00267 
<a name="l00268"></a>00268         QMap&lt;int, QVector&lt;int&gt; &gt; indexes = indexList.getIndexesPositions();
<a name="l00269"></a>00269         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; indexIds.size(); i++)
<a name="l00270"></a>00270                 <span class="keywordflow">if</span> (!indexes.contains(ABS(indexIds[i])))
<a name="l00271"></a>00271                         std::cerr &lt;&lt; <span class="stringliteral">&quot;ERROR, index &quot;</span> &lt;&lt; indexIds[i] &lt;&lt; <span class="stringliteral">&quot; not found in transpose.&quot;</span> &lt;&lt; std::endl;
<a name="l00272"></a>00272 
<a name="l00273"></a>00273         QVector&lt; int &gt; order(indexIds.size());
<a name="l00274"></a>00274         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; order.size(); i++)
<a name="l00275"></a>00275                 order[i] = indexes[ABS(indexIds[i])][0];
<a name="l00276"></a>00276 
<a name="l00277"></a>00277         <span class="keywordflow">return</span> <a class="code" href="classQVTensor.html#a6ca73279da9ca3a3914d385faeac0ccd" title="Change the order of the indexes in the tensor.">transpose</a>(order);
<a name="l00278"></a>00278         }
<a name="l00279"></a>00279 
<a name="l00280"></a>00280 QVector&lt;int&gt; getSorting(<span class="keyword">const</span> QVector&lt;int&gt; &amp;values)
<a name="l00281"></a>00281         {
<a name="l00282"></a>00282         QVector&lt;int&gt; result(values.size()-1), dupe = values;
<a name="l00283"></a>00283         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; values.size() -1; i++)
<a name="l00284"></a>00284                 {
<a name="l00285"></a>00285                 <span class="keywordtype">int</span> pivote = i;
<a name="l00286"></a>00286                 <span class="keywordflow">for</span> (<span class="keywordtype">int</span> j = i+1; j &lt; values.size(); j++)
<a name="l00287"></a>00287                         <span class="keywordflow">if</span> (dupe[pivote] &gt; dupe[j])
<a name="l00288"></a>00288                                 pivote = j;
<a name="l00289"></a>00289                 result[i] = pivote;
<a name="l00290"></a>00290 
<a name="l00291"></a>00291                 <span class="comment">// Swap value of the &#39;pivote&#39;</span>
<a name="l00292"></a>00292                 <span class="keyword">const</span> <span class="keywordtype">int</span> temp = dupe[i];
<a name="l00293"></a>00293                 dupe[i] = dupe[pivote];
<a name="l00294"></a>00294                 dupe[pivote] = temp;
<a name="l00295"></a>00295                 }
<a name="l00296"></a>00296         <span class="keywordflow">return</span> result;
<a name="l00297"></a>00297         }
<a name="l00298"></a>00298 
<a name="l00299"></a>00299 <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> <a class="code" href="classQVTensor.html#a6ca73279da9ca3a3914d385faeac0ccd" title="Change the order of the indexes in the tensor.">QVTensor::transpose</a>(<span class="keyword">const</span> <span class="keywordtype">int</span> index1Position, <span class="keyword">const</span> <span class="keywordtype">int</span> index2Position)<span class="keyword"> const</span>
<a name="l00300"></a>00300 <span class="keyword">        </span>{
<a name="l00301"></a>00301         Q_ASSERT(dims.size() == indexIds.size());
<a name="l00302"></a>00302 
<a name="l00303"></a>00303         <span class="comment">// If both indexes are the same, return the actual tensor</span>
<a name="l00304"></a>00304         <span class="keywordflow">if</span> (index1Position == index2Position)
<a name="l00305"></a>00305                 <span class="keywordflow">return</span> *<span class="keyword">this</span>;
<a name="l00306"></a>00306 
<a name="l00307"></a>00307         QVector &lt;int&gt; order(dims.size());
<a name="l00308"></a>00308         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; order.size(); i++)
<a name="l00309"></a>00309                 order[i] = i;
<a name="l00310"></a>00310 
<a name="l00311"></a>00311         order[MIN(index1Position, index2Position)] = MAX(index1Position, index2Position);
<a name="l00312"></a>00312         order[MAX(index1Position, index2Position)] = MIN(index1Position, index2Position);
<a name="l00313"></a>00313 
<a name="l00314"></a>00314         <span class="keywordflow">return</span> <a class="code" href="classQVTensor.html#a6ca73279da9ca3a3914d385faeac0ccd" title="Change the order of the indexes in the tensor.">transpose</a>(order);
<a name="l00315"></a>00315         }
<a name="l00316"></a>00316 
<a name="l00317"></a>00317 <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> <a class="code" href="classQVTensor.html#a6ca73279da9ca3a3914d385faeac0ccd" title="Change the order of the indexes in the tensor.">QVTensor::transpose</a>(<span class="keyword">const</span> QVector&lt;int&gt; &amp;order)<span class="keyword"> const</span>
<a name="l00318"></a>00318 <span class="keyword">        </span>{
<a name="l00319"></a>00319         Q_ASSERT(dims.size() == indexIds.size());
<a name="l00320"></a>00320 
<a name="l00321"></a>00321         <span class="comment">// TODO: si el orden es el identidad (1, 2, 3, 4, ......, n), devolver copia de este tensor.</span>
<a name="l00322"></a>00322         QVector&lt;int&gt; sorting = getSorting(order);
<a name="l00323"></a>00323 
<a name="l00324"></a>00324         QVTensorValence idxList = <a class="code" href="classQVTensor.html#ada0f3000987c85bbaaa3c02e4b69aada" title="Gets valence of the tensor.">getValence</a>();
<a name="l00325"></a>00325 
<a name="l00326"></a>00326         <span class="keywordtype">bool</span> orderedIndexes = <span class="keyword">true</span>;
<a name="l00327"></a>00327         <span class="keywordtype">int</span> maxIndexPosition = 0;
<a name="l00328"></a>00328         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; sorting.size(); i++)
<a name="l00329"></a>00329                 <span class="keywordflow">if</span> (i != sorting[i])
<a name="l00330"></a>00330                         {
<a name="l00331"></a>00331                         idxList.swap(i, maxIndexPosition = sorting[i]);
<a name="l00332"></a>00332                         orderedIndexes = <span class="keyword">false</span>;
<a name="l00333"></a>00333                         }
<a name="l00334"></a>00334 
<a name="l00335"></a>00335         <span class="comment">// If there are no indexes to move, return the actual tensor</span>
<a name="l00336"></a>00336         <span class="keywordflow">if</span> (orderedIndexes)
<a name="l00337"></a>00337                 <span class="keywordflow">return</span> *<span class="keyword">this</span>;
<a name="l00338"></a>00338 
<a name="l00339"></a>00339         <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> result(idxList);
<a name="l00340"></a>00340 
<a name="l00341"></a>00341         QVTensorIndexator indexator(result.dims);
<a name="l00342"></a>00342         <span class="keyword">const</span> <span class="keywordtype">int</span>       vectorSize = indexator.getStep(maxIndexPosition);
<a name="l00343"></a>00343         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = sorting.size()-1; i &gt;=0; i--)
<a name="l00344"></a>00344                 <span class="keywordflow">if</span> (i != sorting[i])
<a name="l00345"></a>00345                         indexator.swapIndexes(i, sorting[i]);
<a name="l00346"></a>00346 
<a name="l00347"></a>00347         QVTensorIterator tensorIterator(indexator, maxIndexPosition);
<a name="l00348"></a>00348 
<a name="l00349"></a>00349         <span class="keyword">const</span> <span class="keywordtype">double</span>    *srcData = <a class="code" href="classQVTensor.html#a9e75752b76652d2a1ebc64dbc5d0df49" title="Gets a read-only reference to the data buffer of the tensor.">getReadData</a>();
<a name="l00350"></a>00350         <span class="keywordtype">double</span>          *destData = result.getWriteData();
<a name="l00351"></a>00351         <span class="keywordtype">int</span>             destIndexValue = -vectorSize;
<a name="l00352"></a>00352 
<a name="l00353"></a>00353         <span class="keywordflow">do</span> cblas_dcopy(vectorSize, &amp;(srcData[destIndexValue += vectorSize]), 1, &amp;(destData[tensorIterator.getVectorIndex()]),1);
<a name="l00354"></a>00354         <span class="keywordflow">while</span> (tensorIterator.nextVector());
<a name="l00355"></a>00355 
<a name="l00356"></a>00356         <span class="keywordflow">return</span> result;
<a name="l00357"></a>00357         }
<a name="l00358"></a>00358 
<a name="l00359"></a>00359 <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> QVTensor::contract()<span class="keyword"> const</span>
<a name="l00360"></a>00360 <span class="keyword">        </span>{
<a name="l00361"></a>00361         Q_ASSERT(dims.size() == indexIds.size());
<a name="l00362"></a>00362 
<a name="l00363"></a>00363         <span class="keyword">const</span> QMap&lt; int, QVector&lt;int&gt; &gt; map = <a class="code" href="classQVTensor.html#ada0f3000987c85bbaaa3c02e4b69aada" title="Gets valence of the tensor.">getValence</a>().getIndexesPositions();
<a name="l00364"></a>00364 
<a name="l00365"></a>00365         <span class="comment">// Create ordering for indexes, and list of indexes for result tensor.</span>
<a name="l00366"></a>00366         QVector&lt;int&gt; variableIndexesPositions, fixedIndexesPositions;
<a name="l00367"></a>00367         QVector&lt;int&gt; variableDims;
<a name="l00368"></a>00368         QVTensorValence fixedIndexList;
<a name="l00369"></a>00369 
<a name="l00370"></a>00370         <span class="keywordtype">bool</span> dupedIndexes = <span class="keyword">false</span>;
<a name="l00371"></a>00371         QMapIterator&lt; int, QVector&lt;int&gt; &gt; idx(map);
<a name="l00372"></a>00372         <span class="keywordflow">while</span> (idx.hasNext())
<a name="l00373"></a>00373                 {
<a name="l00374"></a>00374                 idx.next();
<a name="l00375"></a>00375                 QVector&lt;int&gt; v = idx.value();
<a name="l00376"></a>00376 
<a name="l00377"></a>00377                 <span class="keywordflow">switch</span>(v.size())
<a name="l00378"></a>00378                         {
<a name="l00379"></a>00379                         <span class="keywordflow">case</span> 1:
<a name="l00380"></a>00380                                 fixedIndexesPositions.append(v[0]);
<a name="l00381"></a>00381                                 fixedIndexList.append(<a class="code" href="classQVTensorIndex.html" title="Indexes for tensors.">QVTensorIndex</a>(dims[v[0]],indexIds[v[0]]));
<a name="l00382"></a>00382                                 <span class="keywordflow">break</span>;
<a name="l00383"></a>00383                         <span class="keywordflow">case</span> 2:
<a name="l00384"></a>00384                                 <span class="keywordflow">if</span> (indexIds[v[0]] != -indexIds[v[1]])
<a name="l00385"></a>00385                                         std::cerr       &lt;&lt; <span class="stringliteral">&quot;ERROR: two index apperances are not covariant: &quot;</span>
<a name="l00386"></a>00386                                                         &lt;&lt; indexIds[v[0]] &lt;&lt; <span class="stringliteral">&quot;, &quot;</span> &lt;&lt; indexIds[v[1]] &lt;&lt; std::endl;
<a name="l00387"></a>00387                                 variableIndexesPositions.append(v[0]);
<a name="l00388"></a>00388                                 variableIndexesPositions.append(v[1]);
<a name="l00389"></a>00389                                 variableDims.append(dims[v[0]]);
<a name="l00390"></a>00390                                 dupedIndexes = <span class="keyword">true</span>;
<a name="l00391"></a>00391                                 <span class="keywordflow">break</span>;
<a name="l00392"></a>00392                         <span class="keywordflow">default</span>:
<a name="l00393"></a>00393                                 std::cerr &lt;&lt; <span class="stringliteral">&quot;ERROR: more than two index apperances in a tensor&quot;</span> &lt;&lt; std::endl;
<a name="l00394"></a>00394                                 <span class="keywordflow">break</span>;
<a name="l00395"></a>00395                         }
<a name="l00396"></a>00396                 }
<a name="l00397"></a>00397 
<a name="l00398"></a>00398         <span class="comment">// If there are no indexes to contract, return the actual tensor</span>
<a name="l00399"></a>00399         <span class="keywordflow">if</span> (!dupedIndexes)
<a name="l00400"></a>00400                 <span class="keywordflow">return</span> *<span class="keyword">this</span>;
<a name="l00401"></a>00401 
<a name="l00402"></a>00402         QVector&lt;int&gt; inverseOrder = variableIndexesPositions + fixedIndexesPositions;
<a name="l00403"></a>00403         QVector&lt;int&gt; order(inverseOrder.size());
<a name="l00404"></a>00404         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; inverseOrder.size(); i++)
<a name="l00405"></a>00405                 order[inverseOrder[i]] = i;
<a name="l00406"></a>00406 
<a name="l00407"></a>00407         <span class="comment">// Transpose original tensor, and create result tensor.</span>
<a name="l00408"></a>00408         <span class="keyword">const</span> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> Transposed = <a class="code" href="classQVTensor.html#a6ca73279da9ca3a3914d385faeac0ccd" title="Change the order of the indexes in the tensor.">transpose</a>(order);
<a name="l00409"></a>00409         <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> result(fixedIndexList);
<a name="l00410"></a>00410 
<a name="l00411"></a>00411         <span class="comment">// Create iterator for variable indexes, and indexator for tensor Transposed</span>
<a name="l00412"></a>00412         QVTensorIterator tensorIterator(variableDims);
<a name="l00413"></a>00413         QVTensorIndexator indexator(Transposed.dims);
<a name="l00414"></a>00414 
<a name="l00415"></a>00415         <span class="keyword">const</span> <span class="keywordtype">double</span>    *srcData = Transposed.<a class="code" href="classQVTensor.html#a9e75752b76652d2a1ebc64dbc5d0df49" title="Gets a read-only reference to the data buffer of the tensor.">getReadData</a>();
<a name="l00416"></a>00416         <span class="keywordtype">double</span>          *destData = result.getWriteData();
<a name="l00417"></a>00417         <span class="keyword">const</span> <span class="keywordtype">int</span>       vectorSize = result.getDataSize();
<a name="l00418"></a>00418 
<a name="l00419"></a>00419         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; vectorSize; i++)
<a name="l00420"></a>00420                 destData[i] = 0;
<a name="l00421"></a>00421 
<a name="l00422"></a>00422         <span class="keywordflow">do</span>      {
<a name="l00423"></a>00423                 <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; variableDims.size(); i++)
<a name="l00424"></a>00424                         {
<a name="l00425"></a>00425                         indexator.setIndex(2*i, tensorIterator.getIndex(i));
<a name="l00426"></a>00426                         indexator.setIndex(2*i+1, tensorIterator.getIndex(i));
<a name="l00427"></a>00427                         }
<a name="l00428"></a>00428 
<a name="l00429"></a>00429                 cblas_daxpy(vectorSize, 1, &amp;(srcData[indexator.getMatrixIndex()]), 1, destData, 1);
<a name="l00430"></a>00430                 }
<a name="l00431"></a>00431         <span class="keywordflow">while</span> (tensorIterator.nextVector());
<a name="l00432"></a>00432 
<a name="l00433"></a>00433         <span class="keywordflow">return</span> result;
<a name="l00434"></a>00434         }
<a name="l00435"></a>00435 
<a name="l00436"></a><a class="code" href="classQVTensor.html#a01609a689d7a7e22092968f45eaaba97">00436</a> <span class="keywordtype">double</span> <a class="code" href="classQVTensor.html#a01609a689d7a7e22092968f45eaaba97" title="Gets the norm2 for tensor.">QVTensor::norm2</a>()<span class="keyword"> const</span>
<a name="l00437"></a>00437 <span class="keyword">        </span>{
<a name="l00438"></a>00438         <span class="keywordflow">return</span> sqrt(cblas_dnrm2(<a class="code" href="classQVTensor.html#aaf731ea26d29371aedf67e02a1f47983" title="Gets the size of the data array.">getDataSize</a>(), <a class="code" href="classQVTensor.html#a9e75752b76652d2a1ebc64dbc5d0df49" title="Gets a read-only reference to the data buffer of the tensor.">getReadData</a>(), 1));
<a name="l00439"></a>00439         };
<a name="l00440"></a>00440 
<a name="l00442"></a>00442 
<a name="l00443"></a><a class="code" href="qvtensor_8cpp.html#a9f6c707bf7e995fe6dd73e3701196345">00443</a> <span class="keywordtype">void</span> <a class="code" href="qvtensor_8cpp.html#a9f6c707bf7e995fe6dd73e3701196345">leviCivitaAux</a>(<span class="keywordtype">double</span> *data, QVTensorIndexator &amp;indexator, <span class="keywordtype">int</span> index, <span class="keywordtype">bool</span> parity = <span class="keyword">true</span>)
<a name="l00444"></a>00444         {
<a name="l00445"></a>00445         <span class="keyword">const</span> <span class="keywordtype">int</span> numIndex = indexator.getNumberOfDimensions();
<a name="l00446"></a>00446 
<a name="l00447"></a>00447         <span class="keywordflow">if</span> (index+1 == numIndex)
<a name="l00448"></a>00448                 {
<a name="l00449"></a>00449                 <span class="comment">/*std::cout &lt;&lt; &quot;leviCivitaAux: indexes &quot; &lt;&lt; std::endl;</span>
<a name="l00450"></a>00450 <span class="comment">                for (int n = 0; n &lt; numIndex; n++)</span>
<a name="l00451"></a>00451 <span class="comment">                        std::cout &lt;&lt; &quot;\t&quot; &lt;&lt; indexator.getIndex(n);</span>
<a name="l00452"></a>00452 <span class="comment">                std::cout &lt;&lt; std::endl;</span>
<a name="l00453"></a>00453 <span class="comment">                std::cout &lt;&lt; &quot;leviCivitaAux: set data &quot; &lt;&lt; indexator.getMatrixIndex() &lt;&lt; std::endl;*/</span>
<a name="l00454"></a>00454 
<a name="l00456"></a>00456                 <span class="keywordtype">int</span> accum = 0;
<a name="l00457"></a>00457                 <span class="keywordflow">for</span> (<span class="keywordtype">int</span> n = 0; n &lt; numIndex; n++)
<a name="l00458"></a>00458                         accum = accum*numIndex +  indexator.getIndex(n);
<a name="l00459"></a>00459 
<a name="l00460"></a>00460                 <span class="comment">//std::cout &lt;&lt; &quot;leviCivitaAux: set data &quot; &lt;&lt; indexator.getMatrixIndex() &lt;&lt; &quot;, &quot; &lt;&lt; accum &lt;&lt; std::endl;</span>
<a name="l00461"></a>00461                 <span class="comment">//data[indexator.getMatrixIndex()] = parity?1:-1;</span>
<a name="l00462"></a>00462                 data[accum] = parity?1:-1;
<a name="l00463"></a>00463                 }
<a name="l00464"></a>00464         <span class="keywordflow">else</span>    {
<a name="l00465"></a>00465                 <a class="code" href="qvtensor_8cpp.html#a9f6c707bf7e995fe6dd73e3701196345">leviCivitaAux</a>(data, indexator, index+1, parity);
<a name="l00466"></a>00466 
<a name="l00467"></a>00467                 <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = index+1; i &lt; numIndex; i++)
<a name="l00468"></a>00468                         {
<a name="l00469"></a>00469                         indexator.swapIndexes(index, i);
<a name="l00470"></a>00470                         <a class="code" href="qvtensor_8cpp.html#a9f6c707bf7e995fe6dd73e3701196345">leviCivitaAux</a>(data, indexator, index+1, !parity);
<a name="l00471"></a>00471                         indexator.swapIndexes(index, i);
<a name="l00472"></a>00472                         }
<a name="l00473"></a>00473                 }
<a name="l00474"></a>00474         }
<a name="l00475"></a>00475 
<a name="l00476"></a><a class="code" href="classQVTensor.html#a9f0d229103588fb0bbbd32676a66888e">00476</a> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> <a class="code" href="classQVTensor.html#a9f0d229103588fb0bbbd32676a66888e" title="Gets Levi Civita symbol tensor.">QVTensor::leviCivita</a>(<span class="keyword">const</span> <span class="keywordtype">int</span> dimension)
<a name="l00477"></a>00477         {
<a name="l00478"></a>00478         QVTensorValence valence;
<a name="l00479"></a>00479 
<a name="l00480"></a>00480         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; dimension; i++)
<a name="l00481"></a>00481                 valence = valence * <a class="code" href="classQVTensorIndex.html" title="Indexes for tensors.">QVTensorIndex</a>(dimension);
<a name="l00482"></a>00482 
<a name="l00483"></a>00483         <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> result(valence);
<a name="l00484"></a>00484 
<a name="l00485"></a>00485         <span class="keywordtype">double</span> *data = result.<a class="code" href="classQVTensor.html#a9d5c2f2d4fd11123354d7568400d2b8e" title="Gets a reference of the data buffer of the tensor for read and write accesses.">getWriteData</a>();
<a name="l00486"></a>00486         <span class="keyword">const</span> <span class="keywordtype">int</span> dataSize = result.<a class="code" href="classQVTensor.html#aaf731ea26d29371aedf67e02a1f47983" title="Gets the size of the data array.">getDataSize</a>();
<a name="l00487"></a>00487         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; dataSize; i++)
<a name="l00488"></a>00488                 data[i] = 0;
<a name="l00489"></a>00489 
<a name="l00490"></a>00490         QVTensorIndexator indexator = result.<a class="code" href="classQVTensor.html#a1b856e5e538e752255d0d49e8509dd66" title="Gets tensor indexator.">getIndexator</a>();
<a name="l00491"></a>00491         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; dimension; i++)
<a name="l00492"></a>00492                 indexator.setIndex(i,i);
<a name="l00493"></a>00493 
<a name="l00494"></a>00494         <a class="code" href="qvtensor_8cpp.html#a9f6c707bf7e995fe6dd73e3701196345">leviCivitaAux</a>(data, indexator, 0);
<a name="l00495"></a>00495 
<a name="l00496"></a>00496         <span class="keywordflow">return</span> result;  
<a name="l00497"></a>00497         }
<a name="l00498"></a>00498 
<a name="l00500"></a>00500 
<a name="l00501"></a>00501 <span class="preprocessor">#include &lt;QString&gt;</span>
<a name="l00502"></a>00502 std::ostream&amp; operator &lt;&lt; ( std::ostream &amp;os, <span class="keyword">const</span> <a class="code" href="classQVTensor.html" title="Implementation of tensors, a generalization for matrices and vectors.">QVTensor</a> &amp;tensor )
<a name="l00503"></a>00503         {
<a name="l00504"></a>00504         <span class="keyword">const</span> QVector&lt;int&gt; dims = tensor.dims, indexIds = tensor.indexIds;
<a name="l00505"></a>00505         <span class="keyword">const</span> <span class="keywordtype">int</span>       numDims = dims.size();
<a name="l00506"></a>00506 
<a name="l00507"></a>00507         Q_ASSERT(dims.size() == indexIds.size());
<a name="l00508"></a>00508 
<a name="l00509"></a>00509         <span class="keywordflow">if</span> (numDims == 0)
<a name="l00510"></a>00510                 {
<a name="l00511"></a>00511                 os &lt;&lt; <span class="stringliteral">&quot;QVTensor &lt;&gt; () [ &quot;</span> &lt;&lt; tensor.<a class="code" href="classQVTensor.html#a9e75752b76652d2a1ebc64dbc5d0df49" title="Gets a read-only reference to the data buffer of the tensor.">getReadData</a>()[0] &lt;&lt; <span class="stringliteral">&quot; ]&quot;</span>;
<a name="l00512"></a>00512                 <span class="keywordflow">return</span> os;
<a name="l00513"></a>00513                 }
<a name="l00514"></a>00514 
<a name="l00515"></a>00515         os &lt;&lt; <span class="stringliteral">&quot;QVTensor &lt;&quot;</span> &lt;&lt; ((indexIds[0]&lt;0)?<span class="stringliteral">&quot;cov &quot;</span>:<span class="stringliteral">&quot;&quot;</span>) &lt;&lt; ABS(indexIds[0]);
<a name="l00516"></a>00516 
<a name="l00517"></a>00517         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i=1; i&lt;numDims; i++)
<a name="l00518"></a>00518                 os &lt;&lt; <span class="stringliteral">&quot;, &quot;</span> &lt;&lt; ((indexIds[i]&lt;0)?<span class="stringliteral">&quot;cov &quot;</span>:<span class="stringliteral">&quot;&quot;</span>) &lt;&lt; ABS(indexIds[i]);
<a name="l00519"></a>00519 
<a name="l00520"></a>00520         os &lt;&lt; <span class="stringliteral">&quot;&gt; (&quot;</span> &lt;&lt; dims[0];
<a name="l00521"></a>00521 
<a name="l00522"></a>00522         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i=1; i&lt;numDims; i++)
<a name="l00523"></a>00523                 os &lt;&lt; <span class="stringliteral">&quot; x &quot;</span> &lt;&lt; dims[i];
<a name="l00524"></a>00524 
<a name="l00525"></a>00525         os &lt;&lt; <span class="stringliteral">&quot;)&quot;</span> &lt;&lt; std::endl;
<a name="l00526"></a>00526 
<a name="l00527"></a>00527         <span class="keyword">const</span> <span class="keywordtype">double</span> *data = tensor.<a class="code" href="classQVTensor.html#a9e75752b76652d2a1ebc64dbc5d0df49" title="Gets a read-only reference to the data buffer of the tensor.">getReadData</a>();
<a name="l00528"></a>00528         QVTensorIterator tensorIterator(dims);
<a name="l00529"></a>00529 
<a name="l00530"></a>00530         <span class="keywordflow">do</span>      {
<a name="l00531"></a>00531                 <span class="keywordflow">if</span> (tensorIterator.getIndex(numDims-1) == 0)
<a name="l00532"></a>00532                         {
<a name="l00533"></a>00533                         <span class="keywordtype">int</span> index = numDims-2;
<a name="l00534"></a>00534                         <span class="keywordflow">while</span>(index &gt;= 0 &amp;&amp; tensorIterator.getIndex(index) == 0)
<a name="l00535"></a>00535                                         index--;
<a name="l00536"></a>00536 
<a name="l00537"></a>00537                         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = index; i&lt; numDims-2; i++)
<a name="l00538"></a>00538                                 os &lt;&lt; qPrintable(QString(4*(i+1), <span class="charliteral">&#39; &#39;</span>)) &lt;&lt; <span class="stringliteral">&quot;[&quot;</span> &lt;&lt; std::endl;
<a name="l00539"></a>00539 
<a name="l00540"></a>00540                         os &lt;&lt; qPrintable(QString(4*(numDims-1), <span class="charliteral">&#39; &#39;</span>)) &lt;&lt; <span class="stringliteral">&quot;[ &quot;</span>;
<a name="l00541"></a>00541                         }
<a name="l00542"></a>00542 
<a name="l00543"></a>00543                 os &lt;&lt; qPrintable(QString(<span class="stringliteral">&quot;%1&quot;</span>).arg(data[tensorIterator.getVectorIndex()], -8, <span class="charliteral">&#39;f&#39;</span>, 6)) &lt;&lt; <span class="stringliteral">&quot; &quot;</span>;
<a name="l00544"></a>00544 
<a name="l00545"></a>00545                 <span class="keywordflow">if</span> (tensorIterator.getIndex(numDims-1) == dims[numDims-1]-1)
<a name="l00546"></a>00546                         {
<a name="l00547"></a>00547                         os &lt;&lt; <span class="stringliteral">&quot;]&quot;</span> &lt;&lt; std::endl;
<a name="l00548"></a>00548                         <span class="keywordtype">int</span> index = numDims-2;
<a name="l00549"></a>00549                         <span class="keywordflow">while</span>(index &gt;= 0 &amp;&amp; tensorIterator.getIndex(index) == dims[index]-1)
<a name="l00550"></a>00550                                 index--;
<a name="l00551"></a>00551 
<a name="l00552"></a>00552                         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = numDims-3; i&gt;=index ; i--)
<a name="l00553"></a>00553                                 os &lt;&lt; qPrintable(QString(4*(i+1), <span class="charliteral">&#39; &#39;</span>)) &lt;&lt; <span class="stringliteral">&quot;]&quot;</span> &lt;&lt; std::endl;
<a name="l00554"></a>00554                         }
<a name="l00555"></a>00555                 } <span class="keywordflow">while</span> (tensorIterator.nextVector());
<a name="l00556"></a>00556 
<a name="l00557"></a>00557         <span class="keywordflow">return</span> os;
<a name="l00558"></a>00558         }
<a name="l00559"></a>00559 
</pre></div></div>
</td></tr></table>

<br /><hr><br />
<center><a href="http://perception.inf.um.es/QVision">QVision framework</a>.
<a href="http://perception.inf.um.es">PARP research group</a>.
Copyright &copy; 2007, 2008, 2009, 2010, 2011.</center>
<br />
</body>
</html>
